/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 * 
 * The Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
 *
 * The Initial Developer of the Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
 * Portions created by Mark A. Kobold are Copyright (C) 2000-2007. All Rights Reserved.
 *
 * Contributor(s): 
 *  Mark A. Kobold [mkobold <at> isqlviewer <dot> com].
 *  
 * If you didn't download this code from the following link, you should check
 * if you aren't using an obsolete version: http://www.isqlviewer.com
 */
package org.isqlviewer.ui.dnd;

import java.awt.HeadlessException;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.sql.SQLException;

import javax.swing.JTree;
import javax.swing.tree.TreePath;

import org.isqlviewer.bookmarks.Bookmark;
import org.isqlviewer.bookmarks.BookmarkFolder;
import org.isqlviewer.bookmarks.BookmarkReference;
import org.isqlviewer.history.HistoricalCommand;
import org.isqlviewer.model.BookmarkTreeModel;
import org.isqlviewer.sql.embedded.EmbeddedDatabase;
import org.isqlviewer.swing.action.SharedActions;
import org.isqlviewer.swing.action.SwingEventManager;

/**
 * Adapter object for handling drop events for bookmarks, folders, and text within a bookmark tree view.
 * <p>
 * 
 * @author Mark A. Kobold &lt;mkobold at isqlviewer dot com&gt;
 * @version 1.0
 */
public class BookmarkTreeDropTarget implements DropTargetListener {

    private static final long serialVersionUID = 1L;
    private SwingEventManager eventManager = null;

    public BookmarkTreeDropTarget(SwingEventManager eventManager) throws HeadlessException {

        this.eventManager = eventManager;
    }

    public void drop(DropTargetDropEvent event) {

        Transferable transferable = event.getTransferable();
        int dropX = event.getLocation().x;
        int dropY = event.getLocation().y;

        JTree bookmarkView = (JTree) event.getDropTargetContext().getComponent();
        TreePath dropTreePath = bookmarkView.getPathForLocation(dropX, dropY);
        BookmarkTreeModel bookmarkModel = (BookmarkTreeModel) bookmarkView.getModel();
        Object dropTarget = (dropTreePath != null ? dropTreePath.getLastPathComponent() : "/");
        BookmarkFolder dropFolder = null;

        if (dropTarget instanceof BookmarkReference) {
            BookmarkReference reference = (BookmarkReference) dropTarget;
            dropFolder = reference.getFolder();
        } else if (dropTarget instanceof BookmarkFolder) {
            dropFolder = (BookmarkFolder) dropTarget;
        }

        if (dropFolder == null) {
            dropFolder = (BookmarkFolder) bookmarkModel.getRoot();
        }

        if (transferable.isDataFlavorSupported(Bookmark.BOOKMARK_FLAVOR)) {
            event.acceptDrop(event.getDropAction());
            dropBookmark(event, transferable, bookmarkModel, dropFolder);
        } else if (transferable.isDataFlavorSupported(HistoricalCommand.FLAVOR)) {
            event.acceptDrop(event.getDropAction());
            HistoricalCommand source = null;
            try {
                source = (HistoricalCommand) transferable.getTransferData(HistoricalCommand.FLAVOR);
            } catch (UnsupportedFlavorException e) {
                event.rejectDrop();
                return;
            } catch (IOException e) {
                event.rejectDrop();
                return;
            }
            String commandText = dropFolder.getPath();
            int eventId = SharedActions.CONVERT_HISTORY_TO_BOOKMARK;
            ActionEvent convertAction = new ActionEvent(source, eventId, commandText);
            eventManager.actionPerformed(convertAction);
            event.dropComplete(true);
        } else if (transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
            event.acceptDrop(event.getDropAction());
            String source = null;
            try {
                source = (String) transferable.getTransferData(DataFlavor.stringFlavor);
            } catch (UnsupportedFlavorException e) {
                event.rejectDrop();
                return;
            } catch (IOException e) {
                event.rejectDrop();
                return;
            }
            String commandText = dropFolder.getPath();
            int eventId = SharedActions.CONVERT_TEXT_TO_BOOKMARK;
            ActionEvent convertAction = new ActionEvent(source, eventId, commandText);
            eventManager.actionPerformed(convertAction);
            event.dropComplete(true);
        } else {
            // unsupported data flavor //
            event.rejectDrop();
        }
    }

    public void dragEnter(DropTargetDragEvent dtde) {

    }

    public void dragExit(DropTargetEvent dte) {

    }

    public void dragOver(DropTargetDragEvent dtde) {

    }

    public void dropActionChanged(DropTargetDragEvent dtde) {

    }

    private void dropBookmark(DropTargetDropEvent event, Transferable transferable, BookmarkTreeModel bookmarkModel,
            BookmarkFolder dropFolder) {

        Bookmark source = null;
        try {
            source = (Bookmark) transferable.getTransferData(Bookmark.BOOKMARK_FLAVOR);
        } catch (UnsupportedFlavorException e) {
            event.rejectDrop();
            return;
        } catch (IOException e) {
            event.rejectDrop();
            return;
        }

        BookmarkFolder sourceFolder = source.getFolder();
        Bookmark bookmark = null;
        boolean doUpdate = false;
        int dndOperation = event.getDropAction();

        switch (dndOperation) {
            case DnDConstants.ACTION_MOVE :
                bookmark = source;
                doUpdate = true;
                break;
            case DnDConstants.ACTION_COPY :
                Bookmark copy = source.clone();
                bookmark = copy;
                break;
            default :
                event.rejectDrop();
                return;
        }

        EmbeddedDatabase database = EmbeddedDatabase.getSharedInstance();
        try {
            if (doUpdate) {
                bookmarkModel.removeBookmark(bookmark);
                bookmarkModel.addBookmark(bookmark, dropFolder);
                database.updateBookmark(bookmark);
            } else {
                bookmarkModel.addBookmark(bookmark, dropFolder);
                database.addBookmark(bookmark);
            }
            event.dropComplete(true);
        } catch (SQLException sourceError) {
            // rollback and reject the drop //
            if (doUpdate) {
                bookmarkModel.removeBookmark(bookmark);
                bookmarkModel.addBookmark(bookmark, sourceFolder);
            } else {
                bookmarkModel.removeBookmark(bookmark);
            }
            bookmarkModel.reload(sourceFolder, bookmark);
            event.dropComplete(false);
        }
    }
}
